{
 "cells": [
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-08-11T07:43:20.201353Z",
     "start_time": "2025-08-11T07:42:07.555554Z"
    }
   },
   "source": [
    "import torch\n",
    "from torch import nn\n",
    "from torchvision.models import resnet50\n",
    "print(list(resnet50(weights='IMAGENET1K_V2').children())[-2])"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Downloading: \"https://download.pytorch.org/models/resnet50-11ad3fa6.pth\" to C:\\Users\\YuBin/.cache\\torch\\hub\\checkpoints\\resnet50-11ad3fa6.pth\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|██████████| 97.8M/97.8M [01:00<00:00, 1.68MB/s]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "AdaptiveAvgPool2d(output_size=(1, 1))\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\n"
     ]
    }
   ],
   "execution_count": 1
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-08-11T07:53:44.756818Z",
     "start_time": "2025-08-11T07:53:44.532376Z"
    }
   },
   "cell_type": "code",
   "source": "print(list(resnet50(weights='IMAGENET1K_V2').children())[:-2])",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[Conv2d(3, 64, kernel_size=(7, 7), stride=(2, 2), padding=(3, 3), bias=False), BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True), ReLU(inplace=True), MaxPool2d(kernel_size=3, stride=2, padding=1, dilation=1, ceil_mode=False), Sequential(\n",
      "  (0): Bottleneck(\n",
      "    (conv1): Conv2d(64, 64, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
      "    (bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "    (conv2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)\n",
      "    (bn2): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "    (conv3): Conv2d(64, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
      "    (bn3): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "    (relu): ReLU(inplace=True)\n",
      "    (downsample): Sequential(\n",
      "      (0): Conv2d(64, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
      "      (1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "    )\n",
      "  )\n",
      "  (1): Bottleneck(\n",
      "    (conv1): Conv2d(256, 64, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
      "    (bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "    (conv2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)\n",
      "    (bn2): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "    (conv3): Conv2d(64, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
      "    (bn3): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "    (relu): ReLU(inplace=True)\n",
      "  )\n",
      "  (2): Bottleneck(\n",
      "    (conv1): Conv2d(256, 64, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
      "    (bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "    (conv2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)\n",
      "    (bn2): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "    (conv3): Conv2d(64, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
      "    (bn3): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "    (relu): ReLU(inplace=True)\n",
      "  )\n",
      "), Sequential(\n",
      "  (0): Bottleneck(\n",
      "    (conv1): Conv2d(256, 128, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
      "    (bn1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "    (conv2): Conv2d(128, 128, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)\n",
      "    (bn2): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "    (conv3): Conv2d(128, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
      "    (bn3): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "    (relu): ReLU(inplace=True)\n",
      "    (downsample): Sequential(\n",
      "      (0): Conv2d(256, 512, kernel_size=(1, 1), stride=(2, 2), bias=False)\n",
      "      (1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "    )\n",
      "  )\n",
      "  (1): Bottleneck(\n",
      "    (conv1): Conv2d(512, 128, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
      "    (bn1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "    (conv2): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)\n",
      "    (bn2): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "    (conv3): Conv2d(128, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
      "    (bn3): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "    (relu): ReLU(inplace=True)\n",
      "  )\n",
      "  (2): Bottleneck(\n",
      "    (conv1): Conv2d(512, 128, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
      "    (bn1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "    (conv2): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)\n",
      "    (bn2): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "    (conv3): Conv2d(128, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
      "    (bn3): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "    (relu): ReLU(inplace=True)\n",
      "  )\n",
      "  (3): Bottleneck(\n",
      "    (conv1): Conv2d(512, 128, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
      "    (bn1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "    (conv2): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)\n",
      "    (bn2): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "    (conv3): Conv2d(128, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
      "    (bn3): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "    (relu): ReLU(inplace=True)\n",
      "  )\n",
      "), Sequential(\n",
      "  (0): Bottleneck(\n",
      "    (conv1): Conv2d(512, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
      "    (bn1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "    (conv2): Conv2d(256, 256, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)\n",
      "    (bn2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "    (conv3): Conv2d(256, 1024, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
      "    (bn3): BatchNorm2d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "    (relu): ReLU(inplace=True)\n",
      "    (downsample): Sequential(\n",
      "      (0): Conv2d(512, 1024, kernel_size=(1, 1), stride=(2, 2), bias=False)\n",
      "      (1): BatchNorm2d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "    )\n",
      "  )\n",
      "  (1): Bottleneck(\n",
      "    (conv1): Conv2d(1024, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
      "    (bn1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "    (conv2): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)\n",
      "    (bn2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "    (conv3): Conv2d(256, 1024, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
      "    (bn3): BatchNorm2d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "    (relu): ReLU(inplace=True)\n",
      "  )\n",
      "  (2): Bottleneck(\n",
      "    (conv1): Conv2d(1024, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
      "    (bn1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "    (conv2): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)\n",
      "    (bn2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "    (conv3): Conv2d(256, 1024, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
      "    (bn3): BatchNorm2d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "    (relu): ReLU(inplace=True)\n",
      "  )\n",
      "  (3): Bottleneck(\n",
      "    (conv1): Conv2d(1024, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
      "    (bn1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "    (conv2): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)\n",
      "    (bn2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "    (conv3): Conv2d(256, 1024, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
      "    (bn3): BatchNorm2d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "    (relu): ReLU(inplace=True)\n",
      "  )\n",
      "  (4): Bottleneck(\n",
      "    (conv1): Conv2d(1024, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
      "    (bn1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "    (conv2): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)\n",
      "    (bn2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "    (conv3): Conv2d(256, 1024, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
      "    (bn3): BatchNorm2d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "    (relu): ReLU(inplace=True)\n",
      "  )\n",
      "  (5): Bottleneck(\n",
      "    (conv1): Conv2d(1024, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
      "    (bn1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "    (conv2): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)\n",
      "    (bn2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "    (conv3): Conv2d(256, 1024, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
      "    (bn3): BatchNorm2d(1024, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "    (relu): ReLU(inplace=True)\n",
      "  )\n",
      "), Sequential(\n",
      "  (0): Bottleneck(\n",
      "    (conv1): Conv2d(1024, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
      "    (bn1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "    (conv2): Conv2d(512, 512, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)\n",
      "    (bn2): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "    (conv3): Conv2d(512, 2048, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
      "    (bn3): BatchNorm2d(2048, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "    (relu): ReLU(inplace=True)\n",
      "    (downsample): Sequential(\n",
      "      (0): Conv2d(1024, 2048, kernel_size=(1, 1), stride=(2, 2), bias=False)\n",
      "      (1): BatchNorm2d(2048, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "    )\n",
      "  )\n",
      "  (1): Bottleneck(\n",
      "    (conv1): Conv2d(2048, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
      "    (bn1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "    (conv2): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)\n",
      "    (bn2): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "    (conv3): Conv2d(512, 2048, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
      "    (bn3): BatchNorm2d(2048, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "    (relu): ReLU(inplace=True)\n",
      "  )\n",
      "  (2): Bottleneck(\n",
      "    (conv1): Conv2d(2048, 512, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
      "    (bn1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "    (conv2): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)\n",
      "    (bn2): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "    (conv3): Conv2d(512, 2048, kernel_size=(1, 1), stride=(1, 1), bias=False)\n",
      "    (bn3): BatchNorm2d(2048, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)\n",
      "    (relu): ReLU(inplace=True)\n",
      "  )\n",
      ")]\n"
     ]
    }
   ],
   "execution_count": 3
  },
  {
   "cell_type": "code",
   "metadata": {
    "collapsed": true,
    "ExecuteTime": {
     "end_time": "2025-08-11T08:24:43.383105Z",
     "start_time": "2025-08-11T08:24:42.275758Z"
    }
   },
   "source": [
    "import torch\n",
    "from torch import nn\n",
    "from torchvision.models import resnet50\n",
    "\n",
    "\n",
    "class DETR(nn.Module):  # 定义DETR类，继承自nn.Module\n",
    "    def __init__(self, num_classes, hidden_dim, nheads,\n",
    "                 num_encoder_layers, num_decoder_layers):\n",
    "        super().__init__()  # 调用基类的初始化方法\n",
    "        # 使用ResNet-50模型的卷积层作为特征提取器，并去掉最后两层，最后两层是自适应池化和全连接层\n",
    "        self.backbone = nn.Sequential(*list(resnet50(weights='IMAGENET1K_V2').children())[:-2])\n",
    "        # 一个投射层，也就把这个 2048 变成256，也就是这层 conv投射层\n",
    "        self.conv = nn.Conv2d(2048, hidden_dim, 1)  # 1x1卷积核，卷积用于降维\n",
    "        self.transformer = nn.Transformer(hidden_dim, nheads,\n",
    "                                          num_encoder_layers, num_decoder_layers,batch_first=True)  # Transformer模块\n",
    "        self.linear_class = nn.Linear(hidden_dim, num_classes + 1)  # 分类器，输出类别数91+1（背景），这个1代表背景\n",
    "        self.linear_bbox = nn.Linear(hidden_dim, 4)  # 边界框回归器，4代表x,y,w,h\n",
    "        self.query_pos = nn.Parameter(torch.rand(100, hidden_dim))  # 可学习的查询位置参数,100个框，用做transformer的decoder的输入\n",
    "        self.row_embed = nn.Parameter(torch.rand(50, hidden_dim // 2))  # 可学习的行嵌入参数 （50，hidden_dim/2）\n",
    "        self.col_embed = nn.Parameter(torch.rand(50, hidden_dim // 2))  # 可学习的列嵌入参数 （50，hidden_dim/2）\n",
    "\n",
    "    def forward(self, inputs):\n",
    "        x = self.backbone(inputs)  # (N, C, H, W)--> (N, 2048, H/32, W/32) (1,2048,25,38)\n",
    "        print(f'Retnet-50 backbone(骨干网络)输出的特征图的shape: {x.shape}')\n",
    "        h = self.conv(x)  # (N, 2048, H/32, W/32)--> (N, hidden_dim, H/32, W/32),降维\n",
    "        print(f'h.shape---{h.shape}')\n",
    "        H, W = h.shape[-2:]  # (N, hidden_dim, H/32, W/32)--> (H/32, W/32) (25, 38)\n",
    "        #将位置编码与特征图的展平版本相结合，并通过Transformer处理，得到预测结果，包括分类结果和边界框回归结果\n",
    "        # self.col_embed[:W]：从 self.col_embed 中取出前 W 个元素，其中 W 是特征图的宽度。这将生成一个形状为 [W, hidden_dim // 2] 的矩阵，表示列的位置编码\n",
    "\n",
    "        # self.row_embed[:H]：从 self.row_embed 中取出前 H 个元素，其中 H 是特征图的高度。这将生成一个形状为 [H, hidden_dim // 2] 的矩阵，表示行的位置编码\n",
    "        pos = torch.cat([\n",
    "            self.col_embed[:W].unsqueeze(0).repeat(H, 1, 1), # (25, 38, hidden_dim/2)\n",
    "            self.row_embed[:H].unsqueeze(1).repeat(1, W, 1), # (25, 38, hidden_dim/2)\n",
    "        ], dim=-1)\n",
    "        print(pos.shape) # (25，38, hidden_dim)\n",
    "        pos = pos.flatten(0, 1).unsqueeze(0)  # (H/32, W/32, hidden_dim)--> ( 1,H*W, hidden_dim)\n",
    "        print(f'pos.shape  {pos.shape}') # (H*W, 1, hidden_dim) (1, 950, 256)\n",
    "        #这里950输入相当于是序列，因为torch的transformer模块要求输入的维度是(S,N,E)，S是序列长度，N是batch大小，E是embedding维度，batch_first 如果为True,那么序列在最前面,flatten(2)代表最后两维展平\n",
    "        h = self.transformer(pos + h.flatten(2).permute(0,2,1), #h展平permute(2,0,1),尺寸变为(1,950, 256)\n",
    "                             self.query_pos.unsqueeze(0))\n",
    "        print(f'输出尺寸：{h.shape}') # (1,100,256)\n",
    "        return self.linear_class(h), self.linear_bbox(h)\n",
    "\n",
    "#这里91是coco数据集的类别数\n",
    "detr = DETR(num_classes=91, hidden_dim=256, nheads=8,\n",
    "            num_encoder_layers=6, num_decoder_layers=6)\n",
    "detr.eval()\n",
    "inputs = torch.randn(1, 3, 800, 1200) #高800宽1200的输入图像\n",
    "logits, bboxes = detr(inputs)\n",
    "logits.shape, bboxes.shape #输出92类+1（背景）的分类结果和边界框回归结果"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Retnet-50 backbone(骨干网络)输出的特征图的shape: torch.Size([1, 2048, 25, 38])\n",
      "h.shape---torch.Size([1, 256, 25, 38])\n",
      "torch.Size([25, 38, 256])\n",
      "pos.shape  torch.Size([1, 950, 256])\n",
      "输出尺寸：torch.Size([1, 100, 256])\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "(torch.Size([1, 100, 92]), torch.Size([1, 100, 4]))"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 4
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-02-11T08:02:37.946050Z",
     "start_time": "2025-02-11T08:02:37.942822Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "950"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "25*38"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
